#!/usr/bin/python
#coding:utf-8
'''
工具类
'''
import numpy as np 
import matplotlib.pyplot as plt
import pandas as pd
from pandas import 	Series,DataFrame 
from sklearn import datasets 
import sys

#保存决策树
import pickle

#标准化和正则化
from sklearn import preprocessing

def showLabels(labels):
    '''
    图形化显示标签
    '''
    lab=list(set(labels))#类别去重

    #创建类别字典
    labelsDict={}
    labelsString=[]
    explode = [] #凸显第几个

    for index in lab:
        labelsDict[index]=0
        labelsString.append(index)
        explode.append(0)
    

    #获取类别个数
    for index in range(len(labels)):
        for lableName in lab:
            if lableName== labels[index]:
                count=labelsDict[lableName]
                count+=1
                labelsDict[lableName]=count
    
    if(len(labelsDict)>10):
        say("标签长度大于10")
        for labName in labelsDict:
            say("标签名："+str(labName)+"  长度："+str(labelsDict[labName]))
    else:
        sizes=[]
        for index in labelsDict:
            sizes.append(labelsDict[index])

        #绘制柱状图
        plt.bar(range(len(sizes)),sizes,color='rgb',tick_label=lab) #color设置条柱颜色 tick_label设置标签
        # 设置数量
        for xx,yy in zip(lab,sizes):
            plt.text(xx, yy+0.1, str(yy), ha='center')  #前两位坐标，第三位名字，第四位文本显示格式
        plt.show();
        
        #绘制饼状图
        explode[0]=0.1
        fig1, ax1 = plt.subplots()
        '''
        labeldistance：文本的位置距离原点有多远，1.1值1.1被半径
        autopct:圆内文本格式，%3.1f%表示小数有三位，整数有一位的浮点数
        shadow:饼是否有阴影
        startangle,起始角度，0表示从0开始逆时针旋转为第一块，一般选择从90度开始比较好看
        pctdistance:百分比的text离圆心的距离
        patches,1_text,p_text,为了得到饼图返回值，p_texts饼图内部文件的，1_testx饼图外label的文本
        '''
        ax1.pie(sizes, explode=explode, labels=labelsString, autopct='%1.1f%%',shadow=True, startangle=90)
        ax1.axis('equal') 
        plt.show()



def showdData(data):
    '''
    说明：
        显示特征数据特性
        可以使用 pandas的describe显示数据
    '''
    size=data.shape[1] #获取列数
    result=[]
    # indexList=['one','two','three','four','five','sex','seven','eight','nine','ten']
    indexList=[]
    for index in range(size):
        indexList.append(index+1)

    for index in range(size):
        listData=data[:,index]
        #最小值 最大值 和 平均值 标准差 方差 协方差
        result.append([listData.min(),listData.max(),listData.sum(),listData.mean(),listData.std(),listData.var(),np.cov(listData)])

    columns = ['max','min','sum','mean','std','var','cov']
    # columns= ['最大值','最小值','和','平均值','标准差','方差','协方差']
    pd.set_option('display.width',800)
    df = pd.DataFrame(result,index = indexList,columns=columns)
    print df

#标准化 
def zScore(data):
    '''
    说明：
        数据标准化处理
        将数据按其属性（按列）减去均值，除以其方差 
    意义：
        使每个特征/列来说所有数据都聚集在0附近，方差为1
    返回：
        transfrom 方法处理数据
    ''' 
    # data = np.array(data,dtype=np.float64)  #数据类型指定
    #preprocessing.scale(data)
    #preprocessing.MinMaxScaler(feature_range=(min,max)) 指定标准化范围，最小值，最大值
    scaler= preprocessing.StandardScaler(copy=True,with_mean=True,with_std=True).fit(data)
    return scaler

#正则化
def normalization(data):
    '''
    说明：
        数据正则化
    意义：
        将每个样本缩放到单位范围，较少出现错误的可能性。可算算法有L1和L2
        L1正则化：使用l1正则化的模型叫Lasso回归
		L2正则化：使用L2正则化的模型叫Ridge回归（岭回归）
    返回：
        transform 处理数据
    '''
    return  preprocessing.Normalizer(norm ='l1').fit(data)  #norm 可选择 l2和l1


#归一化
def scale(data):
    '''
    说明：
        数据归一化
    意义：
        按列减去均值，除以方差
    返回：
        归一化后的数据
    '''
    return preprocessing.scale(data)

# 保存决策树
def saveModel(model,filename):
	pickle.dump(model,open(filename,'wb'))

#加载决策树
def loadModel(filename):	#加载模型
	model = pickle.load(open(filename,'rb'))
	return model

def createData():
    #鸢尾花数据
    iris=datasets.load_iris()
    # print iris.data #得到二维数组
    # x=iris.data[:,:2] #截取前两列

    print '鸢尾花名字',iris.target_names[0]
    x=iris.data
    y=iris.target 
    return x,y  

def main():
    data,lables=createData()

    showLabels(lables)
    # showdData(data)

def say(context):
	type=sys.getfilesystemencoding()
	print context.decode('utf-8').encode(type)   

if __name__ == '__main__':
    main()

